// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// b [author] rhyme_lph
// b [email]  rhymelph@gmail.com
// N [github] https://github.com/rhymelph

import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/generated/a.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/app_colors.dart';
import 'package:finance_app/src/common/app_spaces.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/expense_detail_entity.dart';
import 'package:finance_app/src/entities/format/split_expense_entity.dart';
import 'package:finance_app/src/entities/ocr_attachment_entity.dart';
import 'package:finance_app/src/entities/transaction_entity.dart';
import 'package:finance_app/src/provider/dashboard/contact/business_contact_detail_provider.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/utils/cash_utils.dart';
import 'package:finance_app/src/utils/date_time_utils.dart';
import 'package:finance_app/src/utils/form_utils.dart';
import 'package:finance_app/src/utils/object_utils.dart';
import 'package:finance_app/src/widgets/button/normal_border_button.dart';
import 'package:finance_app/src/widgets/button/normal_popup_button.dart';
import 'package:finance_app/src/widgets/button/normal_text_button.dart';
import 'package:finance_app/src/widgets/common/normal_error_text.dart';
import 'package:finance_app/src/widgets/form/add_form.dart';
import 'package:finance_app/src/widgets/form/form_edit_status_inherited_widget.dart';
import 'package:finance_app/src/widgets/form/icon_currency_price_input_form.dart';
import 'package:finance_app/src/widgets/form/price_form.dart';
import 'package:finance_app/src/widgets/form/status_line_form.dart';
import 'package:finance_app/src/widgets/form/value_select_form.dart';
import 'package:finance_app/src/widgets/common_app_bar.dart';
import 'package:finance_app/src/widgets/form/attach_file_form.dart';
import 'package:finance_app/src/widgets/form/category_gst_amount_form_item.dart';
import 'package:finance_app/src/widgets/form/text_area_input_form.dart';
import 'package:finance_app/src/widgets/input/form_input_field.dart';
import 'package:finance_app/src/widgets/select/normal_radio.dart';
import 'package:finance_app/src/widgets/wrapper/normal_form_wrapper.dart';
import 'package:flutter/material.dart';
import 'package:finance_app/src/provider/dashboard/expense/new_expense_provider.dart';
import 'package:finance_app/src/router_gen/router_meta.dart';
import 'package:tuple/tuple.dart';

export 'package:finance_app/src/entities/transaction_entity.dart';
export 'package:finance_app/src/entities/expense_detail_entity.dart';
export 'package:finance_app/src/entities/ocr_attachment_entity.dart';

@RouterMeta(paramName: "newExpensePage")
class NewExpensePage extends StatefulWidget {
  final TransactionEntity data;
  final ExpenseDetailEntity expenseData;
  final OcrAttachmentOcrData ocrData;
  final bool isSelectMode;
  final bool isHidePaid;
  final List<String> attachments;

  const NewExpensePage(
      {Key key,
      this.data,
      this.attachments,
      this.expenseData,
      this.ocrData,
      this.isSelectMode,
      this.isHidePaid})
      : super(key: key);

  @override
  _NewExpensePageState createState() => _NewExpensePageState();
}

class _NewExpensePageState extends State<NewExpensePage>
    with PagePresenter<NewExpensePage, NewExpenseProvider> {
  String get title => provider.data == null && pageStatus != PageStatus.loading
      ? S.current.new_expense
      : provider.isEdit == true
          ? S.current.edit_expense
          : S.current.expense;

  Widget get rightButton => listBuilder<bool>(
        selector: (_, __) => __.isEdit == false && __.data != null,
        builder: (BuildContext context, bool value, Widget child) =>
            value ? _buildPopButton() : _buildSaveBtn(),
      );

  @override
  PreferredSizeWidget get appBar => getDefaultAppBar(
          titleWidget: listBuilder<Tuple2<ExpenseDetailEntity, bool>>(
            selector: (_, __) => Tuple2(__.data, __.isEdit),
            builder: (BuildContext context,
                    Tuple2<ExpenseDetailEntity, bool> value, Widget child) =>
                Text(title),
          ),
          actions: [
            rightButton,
          ]);

  @override
  void initState() {
    provider.isSelectMode = widget.isSelectMode;
    provider.unit = Config.defaultCurrency;
    if (widget.attachments != null) {
      provider.files.addAll(widget.attachments);
    }
    final pro = Providers.get<BusinessContactDetailProvider>(
        RouterGenProviders.businessContactDetailPage, null);
    if (pro != null) {
      provider.paidTo = pro.contact;
    }
    if (widget.isHidePaid == true) {
      provider.paidUsing = Config.settingData.paidUsing.last;
      if (widget.expenseData == null) {
        provider.onSettingPaidBy();
      }
    }
    provider.init(widget.data?.transactionableId);
    provider.initExpense(widget.expenseData);
    provider.initOcrData(widget.ocrData);
    super.initState();
  }

  Widget _buildPopButton() => listBuilder<bool>(
      selector: (_, __) => __.menuList.length == 0,
      builder: (BuildContext context, bool value, Widget child) =>
          value == true ? Container() : child,
      child: listBuilder<List<String>>(
        selector: (_, __) => List.from(__.menuList),
        builder: (BuildContext context, List<String> value, Widget child) =>
            NormalMorePopupButton(
          onSelect: provider.onSelectMenu,
          menuList: provider.menuList,
        ),
      ));

  Widget _buildSaveBtn() {
    return listBuilder<bool>(
      selector: (_, __) => pageStatus != PageStatus.loading,
      builder: (BuildContext context, bool value, Widget child) => value == true
          ? NormalSaveTextButton(
              onTap: provider.onSave,
            )
          : Container(),
    );
  }

  @override
  Widget wrapperBody(Widget child) {
    return listBuilder<bool>(
      selector: (_, __) => __.isEdit == true || provider.id == null,
      builder: (BuildContext context, bool value, Widget child) =>
          FormEditStatusInheritedWidget(
        isEdit: value,
        child: child,
      ),
      child: child,
    );
  }

  @override
  Widget get buildWidget => ListView(
        children: [
          listBuilder<Tuple4<String, String, bool, bool>>(
            selector: (_, __) => Tuple4(
                __.data?.status,
                __.data?.reimburseStatus,
                __.paidUsing?.key == 'personal' ||
                    __.isPaid == false ||
                    __.data?.status == 'open',
                __.data?.isOverdue == 1),
            builder: (BuildContext context,
                    Tuple4<String, String, bool, bool> value, Widget child) =>
                value.item3
                    ? _buildStatusLine(value.item1, value.item2, value.item4)
                    : Container(),
          ),
          FormStatusWidget(
            enable: Container(),
            disable: listBuilder<String>(
              selector: (_, __) => __.data?.reimbursePaymentType?.name,
              builder: (BuildContext context, String value, Widget child) =>
                  value == null
                      ? Container()
                      : ValueSelectForm(
                          title: S.current.payment_method,
                          valueColor: aceGreenColor,
                          value: value,
                        ),
            ),
          ),
          FormStatusWidget(
            enable: Container(),
            disable: listBuilder<String>(
              selector: (_, __) => __.data?.rejectedReason,
              builder: (BuildContext context, String value, Widget child) =>
                  value == null
                      ? Container()
                      : ValueSelectForm(
                          title: S.current.reasons_optional,
                          valueColor: aceRedColor,
                          value: value,
                        ),
            ),
          ),
          listBuilder<String>(
            selector: (_, __) => __.unit?.key ?? 'SGD',
            builder: (BuildContext context, String value, Widget child) =>
                IconCurrencyPriceInputForm(
              controller: provider.priceController,
              focusNode: provider.priceFocusNode,
              currency: value,
              svgIconPath: A.assetsImagesDashboardAddExpense,
              onChangeCurrency: provider.onChangeUnit,
            ),
          ),
          // 12.UI
          if (widget.isHidePaid != true)
            FormStatusWidget(
              builder: (enable) => listBuilder<bool>(
                selector: (_, __) => __.data?.status == null
                    ? __.isPaid
                    : __.isPaid && __.data?.status == 'closed',
                builder: (BuildContext context, bool value, Widget child) =>
                    listBuilder<int>(
                  selector: (_, __) => __.id,
                  builder: (BuildContext context, int id, Widget child) =>
                      Visibility(
                    visible: (id == null && enable) || !enable,
                    child: NormalFormWrapper(
                      hasBottomBorder: true,
                      topPadding: getDp(18),
                      bottomPadding: getDp(18),
                      child: Row(
                        children: [
                          PressedOpacityButton(
                            onPressed: enable
                                ? () => provider.onChangePaidStatus(true)
                                : () {},
                            child: NormalRadio(
                              title: S.current.paid,
                              minWidth: getDp(142),
                              isSelect: value,
                              isEnable: enable,
                            ),
                          ),
                          PressedOpacityButton(
                            onPressed: enable
                                ? () => provider.onChangePaidStatus(false)
                                : () {},
                            child: NormalRadio(
                              title: S.current.unpaid,
                              isSelect: value == false,
                              isEnable: enable,
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ),
            ),
          listBuilder<String>(
            selector: (_, __) => __.paidTo?.name,
            builder: (BuildContext context, String value, Widget child) =>
                ValueSelectForm(
              title: S.current.paid_to,
              value: value,
              onTap: provider.onChangePaidTo,
            ),
          ),
          listBuilder<bool>(
            selector: (_, __) => __.numberHasError,
            builder: (BuildContext context, bool value, Widget child) =>
                FromInputField(
              controller: provider.expenseNumberController,
              focusNode: provider.expenseFocusNode,
              tip: S.current.expense_number,
              hasError: value,
            ),
          ),
          listBuilder<DateTime>(
            selector: (_, __) => __.date,
            builder: (BuildContext context, DateTime value, Widget child) =>
                ValueSelectForm(
              title: S.current.date,
              value: ObjectUtils.isNullDefaultFormat<DateTime>(value, null,
                  (data) => DateTimeUtils.formatGlobalDateTime(data)),
              onTap: provider.onChangeDate,
            ),
          ),
          listBuilder<bool>(
            selector: (_, __) => __.isPaid,
            builder: (BuildContext context, bool value, Widget child) =>
                value == true ? _buildPaidFrom() : _buildUnPaidForm(),
          ),

          listBuilder<bool>(
              selector: (_, __) => __.isPaid,
              builder: (BuildContext context, bool value, Widget child) =>
                  value ? child : Container(),
              child: listBuilder<String>(
                selector: (_, __) => __.paidUsing?.key,
                builder: (BuildContext context, String value, Widget child) {
                  if (value == 'company') {
                    return listBuilder<String>(
                      selector: (_, __) => __.bankAccount != null
                          ? '${__.bankAccount?.bankName} ${__.bankAccount?.accountNumber ?? ''}'
                          : null,
                      builder:
                          (BuildContext context, String value, Widget child) =>
                              ValueSelectForm(
                        title: S.current.bank_account,
                        value: value,
                        border: Border(
                            top: BorderSide(color: aceGrayColor, width: 0.5)),
                        onTap: provider.onChangeBankAccount,
                      ),
                    );
                  } else if (value == 'personal') {
                    return listBuilder<String>(
                      selector: (_, __) => FormUtils.getEmployeeName(__.paidBy),
                      builder:
                          (BuildContext context, String value, Widget child) =>
                              ValueSelectForm(
                        title: S.current.paid_by,
                        value: value,
                        border: Border(
                            top: BorderSide(color: aceGrayColor, width: 0.5)),
                        onTap: Config.isStaff == true
                            ? null
                            : provider.onChangePaidBy,
                      ),
                    );
                  } else {
                    return Container();
                  }
                },
              )),
          AppSpaces.grayH6,
          listBuilder<int>(
            selector: (_, __) =>
                List<SplitExpenseEntity>.from(__.splitList).length,
            builder: (BuildContext context, int value, Widget child) => value !=
                    0
                ? Column(
                    children: [
                      // AppSpaces.grayH6,
                      ...List.generate(
                          value,
                          (index) => listBuilder<
                                  Tuple5<SplitExpenseEntity, bool, int, int,
                                      String>>(
                                selector: (_, __) => Tuple5(
                                    __.splitList[index],
                                    !__.isEqualPrice,
                                    __.splitList[index].selectCategory?.id,
                                    __.splitList[index].selectTax?.id,
                                    __.splitList[index].amount),
                                builder: (BuildContext context,
                                        Tuple5<SplitExpenseEntity, bool, int,
                                                int, String>
                                            value,
                                        Widget child) =>
                                    PressedOpacityButton(
                                  onPressed: () =>
                                      FormEditStatusInheritedWidget.ofEnable(
                                              context)
                                          ? provider.onSelectItem(
                                              value.item1, 'expense')
                                          : () {},
                                  child: CategoryGstAmountFormItem(
                                    category: value.item1.selectCategory,
                                    tax: value.item1.selectTax,
                                    amount: value.item1.amount,
                                    showHeader: index == 0,
                                    hasError: value.item2,
                                    border: null,
                                  ),
                                ),
                              ))
                    ],
                  )
                : ValueSelectForm(
                    title: S.current.category_amount_gst_rate,
                    onTap: () => provider.onSplitExpense(type: 'expense'),
                  ),
          ),
          listBuilder<bool>(
            selector: (_, __) => __.isEqualPrice,
            builder: (BuildContext context, value, Widget child) => ColoredBox(
              color: Colors.white,
              child: NormalErrorText(
                isVisibility: !value,
                content: S.current
                    .ensure_that_total_category_amount_adds_up_to_total_amount,
              ),
            ),
          ),
          AddForm(
            title: S.current.split_expense,
            onTap: () => provider.onSplitExpense(type: 'expense'),
          ),
          AppSpaces.grayH6,
          NormalFormWrapper(
            child: Column(
              children: [
                listBuilder<double>(
                  selector: (_, __) => __.subTotal,
                  builder: (BuildContext context, double value, Widget child) =>
                      PriceForm(
                    title: S.current.subtotal,
                    amount: CashUtils.formatCashAmount(value),
                  ),
                ),
                SizedBox(
                  height: getDp(25),
                ),
                listBuilder<double>(
                  selector: (_, __) => __.gst,
                  builder: (BuildContext context, double value, Widget child) =>
                      value == 0.00
                          ? Container()
                          : Padding(
                              padding: EdgeInsets.only(bottom: getDp(25)),
                              child: PriceForm(
                                title: S.current.gst,
                                amount: CashUtils.formatCashAmount(value),
                              ),
                            ),
                ),
                listBuilder<double>(
                  selector: (_, __) => __.total,
                  builder: (BuildContext context, double value, Widget child) =>
                      PriceForm(
                    title: S.current.total,
                    amount: CashUtils.formatCashAmount(value),
                  ),
                ),
                buildIncludes(),
              ],
            ),
          ),
          listBuilder<bool>(
            selector: (_, __) => __.data == null,
            builder: (BuildContext context, bool value, Widget child) => value
                ? Container()
                : Column(
                    children: [
                      AppSpaces.grayH05,
                      NormalFormWrapper(
                          child: Column(
                        children: [
                          _buildPayment(),
                          AppSpaces.h20,
                          _buildBalance(),
                        ],
                      )),
                    ],
                  ),
          ),
          AppSpaces.grayH6,
          TextAreaInputForm(
            title: S.current.memo_optional,
            controller: provider.notesController,
            focusNode: provider.notesFocusNode,
          ),
          NormalFormWrapper(
            topPadding: 18,
            child: listBuilder<Tuple2<List<String>, List<OcrAttachmentEntity>>>(
              selector: (_, __) =>
                  Tuple2(List.from(__.files), List.from(__.attachments ?? [])),
              builder: (BuildContext context,
                      Tuple2<List<String>, List<OcrAttachmentEntity>> value,
                      Widget child) =>
                  AttachFileForm(
                onAdd: provider.onAddAttachment,
                files: value.item1,
                onSelectFile: provider.onSelectFile,
                attachments: value.item2,
                onSelectAttachment: provider.onSelectAttachment,
              ),
            ),
          ),
          _buildButtonGroup(),
        ],
      );

  Widget _buildButtonGroup() {
    return listBuilder<List<String>>(
      selector: (_, __) => List.from(__.menuList),
      builder: (BuildContext context, List<String> value, Widget child) =>
          Column(
        children: [
          if (value.contains(S.current.make_payment))
            Padding(
              padding: EdgeInsets.only(bottom: getDp(30)),
              child: NormalBorderButton(
                title: S.current.make_payment,
                onTap: provider.onAddPayment,
                isFit: true,
              ),
            ),
          if (value.contains(S.current.see_payment))
            Padding(
              padding: EdgeInsets.only(bottom: getDp(30)),
              child: NormalBorderButton(
                title: S.current.see_payment,
                onTap: provider.onSeePayment,
                isFit: true,
              ),
            ),
          if (value.contains(S.current.reimburse_now))
            Padding(
              padding: EdgeInsets.only(bottom: getDp(30)),
              child: NormalBorderButton(
                title: S.current.reimburse_now,
                onTap: provider.onReimburseNow,
                isFit: true,
              ),
            ),
          if (value.contains(S.current.reimburse_later))
            Padding(
              padding: EdgeInsets.only(bottom: getDp(30)),
              child: NormalBorderButton(
                title: S.current.reimburse_later_payslip,
                onTap: provider.onReimburseLater,
                isFit: true,
              ),
            ),
          if (value.contains(S.current.reject))
            Padding(
              padding: EdgeInsets.only(bottom: getDp(30)),
              child: NormalBorderButton(
                title: S.current.reject,
                onTap: provider.onReject,
                isFit: true,
              ),
            ),
        ],
      ),
    );
  }

  Widget _buildUnPaidForm() {
    return listBuilder<String>(
      selector: (_, __) => DateTimeUtils.formatGlobalDateTime(__.dueDate),
      builder: (BuildContext context, String value, Widget child) =>
          ValueSelectForm(
        title: S.current.due_date,
        value: value,
        onTap: provider.onChangeDueDate,
        border: null,
      ),
    );
  }

  Column _buildPaidFrom() {
    return Column(
      children: [
        listBuilder<String>(
          selector: (_, __) => __.paymentMethod?.name,
          builder: (BuildContext context, String value, Widget child) =>
              ValueSelectForm(
            title: S.current.payment_method,
            value: value,
            onTap: provider.onSelectPaymentMethod,
          ),
        ),
        listBuilder<String>(
          selector: (_, __) => __.paidUsing?.name,
          builder: (BuildContext context, String value, Widget child) =>
              ValueSelectForm(
            title: S.current.paid_using,
            value: value,
            onTap:
                widget.isHidePaid == true ? null : provider.onChangePaidUsing,
            border: null,
          ),
        ),
      ],
    );
  }

  Widget _buildPayment() {
    return listBuilder<num>(
      selector: (_, __) => (__.data.total ?? 0) - __.data.unpaid,
      builder: (BuildContext context, num value, Widget child) => PriceForm(
        title: S.current.payment,
        textColor: value != 0 ? aceGreenColor : null,
        amount: '- ${CashUtils.formatCashAmount(value)}',
      ),
    );
  }

  Widget _buildBalance() {
    return listBuilder<num>(
      selector: (_, __) => __.data.unpaid,
      builder: (BuildContext context, num value, Widget child) => PriceForm(
        title: S.current.balance,
        textColor: value == 0 ? aceGreenColor : null,
        amount: CashUtils.formatCashAmount(value),
      ),
    );
  }

  Widget buildIncludes() {
    return Align(
      alignment: Alignment.centerRight,
      child: listBuilder<double>(
          builder: (BuildContext context, double value, Widget child) =>
              Config.currentCompany.enableGst == 0
                  ? Container()
                  : Container(
                      padding: EdgeInsets.only(top: 2),
                      child: Text(
                        '${S.current.includes_gst} ${CashUtils.formatCashAmount(value)}',
                        style: TextStyle(
                          color: aceDarkGrayColor,
                          fontSize: getSp(14),
                          fontWeight: FontWeight.w400,
                          height: 1,
                        ),
                      ),
                    ),
          selector: (_, __) => __.includesGST),
    );
  }

  Widget _buildStatusLine(String item1, String item2, bool isOverdue) =>
      StatusLineForm(
        status: item1 == 'closed' && provider.isPaid
            ? (item2 == 'na' ? item1 : item2)
            : (isOverdue ? 'Overdue' : item1),
        model: ReimburseModel.expense,
        unpaid: provider.paidUsing?.key == 'personal' ? 0 : 1,
      );
}
